//
//  UIButton+Ext.swift
//  TTCOM-iOS
//
//  Created by Toj on 11/3/22.
//

import UIKit

public extension UIButton {
    
    var btn_setImage: UIImage? {
        set { setImage(newValue, for: .normal) }
        get { return imageView?.image }
    }
    
    func btn_setImage(named: UIImage? = nil) {
        setImage(named, for: .normal)
    }
    
    func btn_setImage(named: String, for state: UIControl.State = .normal) {
        setImage(named.to_image, for: state)
    }
    
    var st_isEmpty: Bool {
        return btn_isEmpty
    }
    
    var btn_isEmpty: Bool {
        let text = titleLabel?.text ?? ""
        let attributedText = titleLabel?.attributedText
        return text.count == 0 && attributedText == nil
    }
}

private var btn_runtime_associated_contentInset_key = "btn_associated_contentInset_key"
extension UIButton {
    
    public var btn_contentInsets: UIEdgeInsets {
        get {
            let associatedValue = objc_getAssociatedObject(self, &btn_runtime_associated_contentInset_key) as? UIEdgeInsets
            return associatedValue ?? .zero
        }
        set {
            objc_setAssociatedObject(self, &btn_runtime_associated_contentInset_key, newValue, .OBJC_ASSOCIATION_ASSIGN)
        }
    }
    
    open override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
        let insets = btn_contentInsets
        if insets.st_isZero {
            return super.point(inside: point, with: event)
        }
        
        let rect = bounds.inset(by: insets)
        return CGRectContainsPoint(rect, point)
    }
}

extension UIButton: STPreparingProtocol {
    
    private struct runtime_prepar_event_key {
        static var timeInterval = "prepar_event_timeInterval_key"
        static var timeWait   = "prepar_event_timeWait_key"
    }
    
    private var st_eventTimeInterval: TimeInterval {
        set {
            objc_setAssociatedObject(self, &runtime_prepar_event_key.timeInterval, newValue, .OBJC_ASSOCIATION_ASSIGN)
        }
        get {
            let interval = (objc_getAssociatedObject(self, &runtime_prepar_event_key.timeInterval) as? TimeInterval) ?? 0.5
            return interval
        }
    }
    
    private var st_isEventWaiting: Bool {
        set {
            objc_setAssociatedObject(self, &runtime_prepar_event_key.timeWait, newValue, .OBJC_ASSOCIATION_ASSIGN)
        }
        get {
            let isBuffer = (objc_getAssociatedObject(self, &runtime_prepar_event_key.timeWait) as? Bool) ?? false
            return isBuffer
        }
    }
    
    public static func preparInitialize() {
        let o_selector = #selector(UIButton.sendAction(_:to:for:))
        let n_selector = #selector(n_sendAction(_:to:for:))
        
        guard let o_method = class_getInstanceMethod(UIButton.self, o_selector),
              let n_method = class_getInstanceMethod(UIButton.self, n_selector)
        else { return }
        
        if class_addMethod(
            UIButton.self,
            o_selector,
            method_getImplementation(n_method),
            method_getTypeEncoding(n_method)
        ) {
            class_replaceMethod(UIButton.self,
                                n_selector,
                                method_getImplementation(o_method),
                                method_getTypeEncoding(o_method)
            )
            return
        }
        method_exchangeImplementations(o_method, n_method)
    }
    
    /// 在这个方法中
    @objc private func n_sendAction(_ action: Selector, to target: Any?, for event: UIEvent?) {
        guard !st_isEventWaiting else { return }
        st_isEventWaiting = true
        
        n_sendAction(action, to: target, for: event)
        // 延时
        DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + st_eventTimeInterval, execute: {
            self.st_isEventWaiting = false
        })
    }
}

